package com.iflytek.jzcpx.procuracy.ocr.common.util.pti.impl;

import com.iflytek.jzcpx.procuracy.ocr.common.util.pti.PtoI;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.UUID;
import com.iflytek.jzcpx.procuracy.ocr.common.util.ttj.impl.Im4JTToJImpl;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Component
public class GsPtoIImpl
        implements PtoI {
    private static final Logger LOGGER = LoggerFactory.getLogger(GsPtoIImpl.class);
    private static final String SVC_GS_DIR = String.format("%s/../lib/", new Object[] { System.getProperty("user.dir") });

    private static final String GS_WORK_DIR = String.format("%s", new Object[] { System.getProperty("user.dir") });
    private static String GS_DEFAULT_EXEC_FILE_PATH;

    @Value("${tuling.ocr.external.gs.path:}")
    private String externalGsAbsPath;

    static  {
        String bitType = System.getProperty("sun.arch.data.model");
        if ("64".equals(bitType)) {
            GS_DEFAULT_EXEC_FILE_PATH = SVC_GS_DIR + "gs-927-linux-x86_64";
        } else if ("32".equals(bitType)) {
            GS_DEFAULT_EXEC_FILE_PATH = SVC_GS_DIR + "gs-927-linux-x86";
        } else {
            GS_DEFAULT_EXEC_FILE_PATH = "";
        }
    }

    public List<byte[]> pdfToImages(byte[] pdfFileBa) throws Exception {
        long start = System.currentTimeMillis();

        String pdfFileNameWithoutSuffix = UUID.randomUUID().toString();
        String pdfFileName = String.format("%s.pdf", new Object[] { pdfFileNameWithoutSuffix });
        String pdfFileAbsPath = GS_WORK_DIR + File.separator + pdfFileName;
        String imageName = String.format("%s-%s.jpg", new Object[] { pdfFileNameWithoutSuffix, "%d" });
        File folderForSaveImages = new File(GS_WORK_DIR + File.separator + pdfFileNameWithoutSuffix);
        boolean mkdirsOk = folderForSaveImages.mkdirs();
        if (!mkdirsOk) {
            LOGGER.error("create folder for save images failed, can't execute [gs], return null.");
            return null;
        }
        String imageFileAbsPath = folderForSaveImages.getAbsolutePath() + File.separator + imageName;

        File pdfFile = new File(pdfFileAbsPath);
        File imageFile = new File(imageFileAbsPath);

        boolean writeOk = writeBaToFile(pdfFileBa, pdfFile);
        if (!writeOk) {
            throw new Exception("write pdf byte array to file exception");
        }

        if (!StringUtils.isEmpty(this.externalGsAbsPath)) {
            GS_DEFAULT_EXEC_FILE_PATH = this.externalGsAbsPath;
        }
        List<byte[]> ret = (List)new ArrayList<>();
        try {
            (new GsCmdUtil(GS_DEFAULT_EXEC_FILE_PATH)).generateImage(null, pdfFile, 300, imageFile);
        } catch (Exception e) {
            LOGGER.error("convert pdf to image failed.", e);
        } finally {
            boolean deleteOk = pdfFile.delete();
            if (!deleteOk) {
                LOGGER.error("delete pef file failed. file abs path: {}", pdfFile.getAbsolutePath());
            }
            ret = Im4JTToJImpl.readFilesBytes(folderForSaveImages);
            FileUtils.deleteDirectory(folderForSaveImages);
        }
        LOGGER.info("command line execute [gs] elapsed time: {}ms", Long.valueOf(System.currentTimeMillis() - start));
        return ret;
    }

    private boolean writeBaToFile(byte[] pdfFileBa, File pdfFile) {
        boolean ret = true;
        try (OutputStream os = new FileOutputStream(pdfFile)) {
            os.write(pdfFileBa);
        } catch (IOException e) {
            LOGGER.error("can't write byte array to pdf file", e);
            ret = false;
        }
        return ret;
    }


    public static void numericSortFileName(File[] fa) {
        if (fa.length <= 1) {
            return;
        }

        Arrays.sort(fa, (Comparator<? super File>)new Object());
    }
}
